/*--------------------------------------------------------------
user_tx_s_axis_tuser:
[63:48]---tx_target_port
[47:16]---tx_target_ip
[15:0]---tx_data_len

user_rx_m_axis_tuser:
[63:48]---rx_source_port
[47:16]---rx_source_ip
[15:0]---rx_data_len
--------------------------------------------------------------*/
//`define UDP
`define TCP

module ethernet_top #(
   parameter   SOURCE_PORT       = 16'd5001                    ,   
   parameter   SOURCE_IP         = {8'd192,8'd168,8'd7,8'd11}  ,
   parameter   SOURCE_IP_MASK    = {8'd255,8'd255,8'd255,8'd0} ,
   parameter   SOURCE_MAC        = 48'h11_22_33_44_55_66       ,         
   parameter   MAC_CRC_ON        = 1                               
)(
   input                         i_clk                         ,
   input                         i_rst                         , 
   input                         i_config_req                  ,
   input    [15: 0]              i_config_source_port          ,
   input    [31: 0]              i_config_source_ip            ,
   input    [31: 0]              i_config_source_ip_mask       ,
   input    [47: 0]              i_config_source_mac           ,
   input                         user_tx_s_axis_tvalid         ,
   input    [7 : 0]              user_tx_s_axis_tdata          ,
   output                        user_tx_s_axis_tready         ,
   input                         user_tx_s_axis_tlast          ,
   input    [67: 0]              user_tx_s_axis_tuser          ,
   output                        user_rx_m_axis_tvalid         ,
   output   [7 : 0]              user_rx_m_axis_tdata          ,
   output                        user_rx_m_axis_tlast          ,
   output   [63: 0]              user_rx_m_axis_tuser          ,
   input    [7 : 0]              i_gmii_rxdata                 ,
   input                         i_gmii_rxvalid                ,
   output   [7 : 0]              o_gmii_txdata                 ,
   output                        o_gmii_txvalid                
);
 
   logic                         arp_req                       ;
   logic [31: 0]                 arp_req_ip                    ;         
   logic [47: 0]                 arp_info_mac0                 ;
   logic [31: 0]                 arp_info_ip0                  ;
   logic [47: 0]                 arp_info_mac1                 ;
   logic [31: 0]                 arp_info_ip1                  ;
   logic                         tcp_user_axis_tx_tvalid       ;
   logic [7 : 0]                 tcp_user_axis_tx_tdata        ;      
   logic                         tcp_user_axis_tx_tready       ;    
   logic                         tcp_user_axis_tx_tlast        ;  
   logic [67: 0]                 tcp_user_axis_tx_tuser        ;  
   logic                         udp_user_axis_tx_tvalid       ;
   logic [7 : 0]                 udp_user_axis_tx_tdata        ;      
   logic                         udp_user_axis_tx_tready       ;    
   logic                         udp_user_axis_tx_tlast        ;  
   logic [63: 0]                 udp_user_axis_tx_tuser        ;  
   logic                         tcp_axis_tx_tvalid            ;
   logic [7 : 0]                 tcp_axis_tx_tdata             ;      
   logic                         tcp_axis_tx_tready            ;    
   logic                         tcp_axis_tx_tlast             ;  
   logic [55: 0]                 tcp_axis_tx_tuser             ;  
   logic                         udp_axis_tx_tvalid            ;
   logic [7 : 0]                 udp_axis_tx_tdata             ;      
   logic                         udp_axis_tx_tready            ;    
   logic                         udp_axis_tx_tlast             ;  
   logic [55: 0]                 udp_axis_tx_tuser             ;  
   logic                         icmp_axis_tx_tvalid           ;
   logic [7: 0]                  icmp_axis_tx_tdata            ;
   logic                         icmp_axis_tx_tready           ; 
   logic                         icmp_axis_tx_tlast            ;
   logic [55: 0]                 icmp_axis_tx_tuser            ;
   logic                         ip_user_axis_rx_tvalid        ;
   logic [7 : 0]                 ip_user_axis_rx_tdata         ;
   logic                         ip_user_axis_rx_tlast         ;
   logic [71: 0]                 ip_user_axis_rx_tuser         ;
   logic                         ip_user_axis_tx_tvalid        ;
   logic [7 : 0]                 ip_user_axis_tx_tdata         ;
   logic                         ip_user_axis_tx_tready        ;
   logic                         ip_user_axis_tx_tlast         ;
   logic [55: 0]                 ip_user_axis_tx_tuser         ;
   logic                         ip_axis_tx_tvalid             ;
   logic [7 : 0]                 ip_axis_tx_tdata              ;
   logic                         ip_axis_tx_tready             ;
   logic                         ip_axis_tx_tlast              ;
   logic [64: 0]                 ip_axis_tx_tuser              ;
   logic                         arp_axis_tx_tvalid            ;
   logic [7 : 0]                 arp_axis_tx_tdata             ;
   logic                         arp_axis_tx_tready            ;
   logic                         arp_axis_tx_tlast             ;
   logic [64: 0]                 arp_axis_tx_tuser             ;
   logic [47: 0]                 arp_set_target_mac            ;
   logic                         arp_set_target_mac_valid      ;
   logic                         mac_user_axis_rx_tvalid       ;
   logic [7 : 0]                 mac_user_axis_rx_tdata        ;
   logic                         mac_user_axis_rx_tlast        ;
   logic [32: 0]                 mac_user_axis_rx_tuser        ;
   logic                         mac_user_axis_tx_tvalid       ;
   logic [7 : 0]                 mac_user_axis_tx_tdata        ;
   logic                         mac_user_axis_tx_tready       ;
   logic                         mac_user_axis_tx_tlast        ;
   logic [64: 0]                 mac_user_axis_tx_tuser        ;



   // ila128_bit ila128_bit_top(
   //      .clk    ( i_clk),
   //      .probe0 ( {
   //                user_tx_s_axis_tvalid,
   //                user_tx_s_axis_tdata ,
   //                user_tx_s_axis_tready,
   //                user_tx_s_axis_tlast ,
   //                tcp_user_axis_tx_tuser[67:64],
   //                tcp_user_axis_tx_tvalid,
   //                tcp_user_axis_tx_tdata ,
   //                tcp_user_axis_tx_tready,
   //                tcp_user_axis_tx_tlast ,
   //                tcp_axis_tx_tvalid,
   //                tcp_axis_tx_tdata ,
   //                tcp_axis_tx_tready,
   //                tcp_axis_tx_tlast ,
   //                ip_user_axis_tx_tvalid ,
   //                ip_user_axis_tx_tdata  ,
   //                ip_user_axis_tx_tready ,
   //                ip_user_axis_tx_tlast  ,
   //                ip_axis_tx_tvalid,
   //                ip_axis_tx_tdata ,
   //                ip_axis_tx_tready,
   //                ip_axis_tx_tlast ,
   //                mac_user_axis_tx_tvalid,
   //                mac_user_axis_tx_tdata ,
   //                mac_user_axis_tx_tready,
   //                mac_user_axis_tx_tlast ,
   //                mac_user_axis_tx_tuser[7:0] ,
   //                o_gmii_txdata ,
   //                o_gmii_txvalid,
   //                icmp_axis_tx_tvalid,
   //                icmp_axis_tx_tdata ,
   //                icmp_axis_tx_tready,
   //                icmp_axis_tx_tlast ,
   //                arp_axis_tx_tvalid            ,
   //                arp_axis_tx_tdata             ,
   //                arp_axis_tx_tready            ,
   //                arp_axis_tx_tlast             ,
   //                mac_user_axis_rx_tvalid ,
   //                mac_user_axis_rx_tdata,  
   //                mac_user_axis_rx_tlast ,
   //                ip_user_axis_rx_tvalid        ,
   //                ip_user_axis_rx_tdata         ,
   //                ip_user_axis_rx_tlast         
                  
   //                })

   //  );

   /*-----------------------------------------------------------
                     tx  check
   ------------------------------------------------------------*/
   user_tx_check #(
      .SOURCE_IP                 (SOURCE_IP)                                          
   )user_tx_check(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_ip           ( i_config_source_ip          ),
      .i_set_source_valid        ( i_config_req                ),
      .i_arp_info_ip0            ( arp_info_ip0                ),
      .i_arp_info_ip1            ( arp_info_ip1                ),   
      .o_arp_req                 ( arp_req                     ),
      .o_arp_req_ip              ( arp_req_ip                  ),
      .s_axis_tvalid             ( user_tx_s_axis_tvalid       ),
      .s_axis_tdata              ( user_tx_s_axis_tdata        ),
      .s_axis_tready             ( user_tx_s_axis_tready       ),
      .s_axis_tlast              ( user_tx_s_axis_tlast        ),
      .s_axis_tuser              ( user_tx_s_axis_tuser        ),
      `ifdef UDP
      .m_axis_tvalid             ( udp_user_axis_tx_tvalid     ),
      .m_axis_tdata              ( udp_user_axis_tx_tdata      ),
      .m_axis_tready             ( udp_user_axis_tx_tready     ),
      .m_axis_tlast              ( udp_user_axis_tx_tlast      ),
      .m_axis_tuser              ( udp_user_axis_tx_tuser      )
      `endif
      `ifdef TCP
      .m_axis_tvalid             ( tcp_user_axis_tx_tvalid     ),
      .m_axis_tdata              ( tcp_user_axis_tx_tdata      ),
      .m_axis_tready             ( tcp_user_axis_tx_tready     ),
      .m_axis_tlast              ( tcp_user_axis_tx_tlast      ),
      .m_axis_tuser              ( tcp_user_axis_tx_tuser      )
      `endif
   );
   /*-----------------------------------------------------------
                     ENTHERNET TCP LAYER
   ------------------------------------------------------------*/
   `ifdef TCP
   ethernet_tcp_top #(
      .SOURCE_PORT               ( SOURCE_PORT                 ),
      .SOURCE_IP                 ( SOURCE_IP                   )    
   )ethernet_tcp_top_inst(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_port_valid   ( i_config_req                ),
      .i_set_source_port         ( i_config_source_port        ),
      .i_set_source_ip_valid     ( i_config_req                ),
      .i_set_source_ip           ( i_config_source_ip          ),
      .user_tcp_m_axis_tvalid    ( user_rx_m_axis_tvalid       ),
      .user_tcp_m_axis_tdata     ( user_rx_m_axis_tdata        ),
      .user_tcp_m_axis_tlast     ( user_rx_m_axis_tlast        ),
      .user_tcp_m_axis_tuser     ( user_rx_m_axis_tuser        ),  
      .user_tcp_s_axis_tvalid    ( tcp_user_axis_tx_tvalid     ),
      .user_tcp_s_axis_tdata     ( tcp_user_axis_tx_tdata      ),
      .user_tcp_s_axis_tready    ( tcp_user_axis_tx_tready     ),
      .user_tcp_s_axis_tlast     ( tcp_user_axis_tx_tlast      ),
      .user_tcp_s_axis_tuser     ( tcp_user_axis_tx_tuser      ),
      .tcp_s_axis_tvalid         ( ip_user_axis_rx_tvalid      ),
      .tcp_s_axis_tdata          ( ip_user_axis_rx_tdata       ),
      .tcp_s_axis_tlast          ( ip_user_axis_rx_tlast       ),
      .tcp_s_axis_tuser          ( ip_user_axis_rx_tuser       ), 
      .tcp_m_axis_tvalid         ( tcp_axis_tx_tvalid          ),
      .tcp_m_axis_tdata          ( tcp_axis_tx_tdata           ),
      .tcp_m_axis_tready         ( tcp_axis_tx_tready          ),
      .tcp_m_axis_tlast          ( tcp_axis_tx_tlast           ),
      .tcp_m_axis_tuser          ( tcp_axis_tx_tuser           )
   );
   `endif


   /*-----------------------------------------------------------
                     ENTHERNET UDP LAYER
   ------------------------------------------------------------*/
   `ifdef UDP
   ethernet_udp_top #(
      .SOURCE_PORT               ( SOURCE_PORT                 )
   )ethernet_udp_top_inst (
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_port_valid   ( i_config_req                ),
      .i_set_source_port         ( i_config_source_port        ),
      .user_udp_m_axis_tvalid    ( user_rx_m_axis_tvalid       ),
      .user_udp_m_axis_tdata     ( user_rx_m_axis_tdata        ),
      .user_udp_m_axis_tlast     ( user_rx_m_axis_tlast        ),
      .user_udp_m_axis_tuser     ( user_rx_m_axis_tuser        ),
      .user_udp_s_axis_tvalid    ( udp_user_axis_tx_tvalid     ),
      .user_udp_s_axis_tdata     ( udp_user_axis_tx_tdata      ),
      .user_udp_s_axis_tready    ( udp_user_axis_tx_tready     ),
      .user_udp_s_axis_tlast     ( udp_user_axis_tx_tlast      ),
      .user_udp_s_axis_tuser     ( udp_user_axis_tx_tuser      ),
      .udp_s_axis_tvalid         ( ip_user_axis_rx_tvalid      ),
      .udp_s_axis_tdata          ( ip_user_axis_rx_tdata       ),
      .udp_s_axis_tlast          ( ip_user_axis_rx_tlast       ),
      .udp_s_axis_tuser          ( ip_user_axis_rx_tuser       ),
      .udp_m_axis_tvalid         ( udp_axis_tx_tvalid          ),
      .udp_m_axis_tdata          ( udp_axis_tx_tdata           ),
      .udp_m_axis_tready         ( udp_axis_tx_tready          ),
      .udp_m_axis_tlast          ( udp_axis_tx_tlast           ),
      .udp_m_axis_tuser          ( udp_axis_tx_tuser           )
   );
   `endif
   
   /*-----------------------------------------------------------
                     ENTHERNET ICMP LAYER
   ------------------------------------------------------------*/
   ethernet_icmp_top ethernet_icmp_top_inst(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .s_axis_tvalid             ( ip_user_axis_rx_tvalid      ),
      .s_axis_tdata              ( ip_user_axis_rx_tdata       ),
      .s_axis_tlast              ( ip_user_axis_rx_tlast       ),
      .s_axis_tuser              ( ip_user_axis_rx_tuser       ),
      .m_axis_tvalid             ( icmp_axis_tx_tvalid         ),
      .m_axis_tdata              ( icmp_axis_tx_tdata          ),
      .m_axis_tready             ( icmp_axis_tx_tready         ),
      .m_axis_tlast              ( icmp_axis_tx_tlast          ),
      .m_axis_tuser              ( icmp_axis_tx_tuser          ) 
   );

   /*-----------------------------------------------------------
                     mac tx arbitriter
   ------------------------------------------------------------*/
   arbiter2to1 ip_tx_arbiter2to1(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .s_axis_tvalid_0           ( icmp_axis_tx_tvalid          ),
      .s_axis_tdata_0            ( icmp_axis_tx_tdata           ),
      .s_axis_tready_0           ( icmp_axis_tx_tready          ),
      .s_axis_tlast_0            ( icmp_axis_tx_tlast           ),
      .s_axis_tuser_0            ( icmp_axis_tx_tuser           ),
      `ifdef TCP
      .s_axis_tvalid_1           ( tcp_axis_tx_tvalid           ),
      .s_axis_tdata_1            ( tcp_axis_tx_tdata            ),
      .s_axis_tready_1           ( tcp_axis_tx_tready           ),
      .s_axis_tlast_1            ( tcp_axis_tx_tlast            ),
      .s_axis_tuser_1            ( tcp_axis_tx_tuser            ),
      `endif
      `ifdef UDP
      .s_axis_tvalid_1           ( udp_axis_tx_tvalid           ),
      .s_axis_tdata_1            ( udp_axis_tx_tdata            ),
      .s_axis_tready_1           ( udp_axis_tx_tready           ),
      .s_axis_tlast_1            ( udp_axis_tx_tlast            ),
      .s_axis_tuser_1            ( udp_axis_tx_tuser            ),
      `endif
      .m_axis_tvalid             ( ip_user_axis_tx_tvalid       ),
      .m_axis_tdata              ( ip_user_axis_tx_tdata        ),
      .m_axis_tready             ( ip_user_axis_tx_tready       ),
      .m_axis_tlast              ( ip_user_axis_tx_tlast        ),
      .m_axis_tuser              ( ip_user_axis_tx_tuser        )
   );

   /*-----------------------------------------------------------
                     ENTHERNET IP LAYER
   ------------------------------------------------------------*/
   ethernet_ip_top #(
      .SOURCE_IP                 ( SOURCE_IP                   ),
      .SOURCE_IP_MASK            ( SOURCE_IP_MASK              )
   )ethernet_ip_top_inst(  
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_ip_valid     ( i_config_req                ),
      .i_set_source_ip           ( i_config_source_ip          ),
      .i_set_source_ip_mask      ( i_config_source_ip_mask     ),
      .ip_user_m_axis_tvalid     ( ip_user_axis_rx_tvalid      ),
      .ip_user_m_axis_tdata      ( ip_user_axis_rx_tdata       ),
      .ip_user_m_axis_tlast      ( ip_user_axis_rx_tlast       ),
      .ip_user_m_axis_tuser      ( ip_user_axis_rx_tuser       ),
      .ip_user_s_axis_tvalid     ( ip_user_axis_tx_tvalid      ),
      .ip_user_s_axis_tdata      ( ip_user_axis_tx_tdata       ),
      .ip_user_s_axis_tready     ( ip_user_axis_tx_tready      ),
      .ip_user_s_axis_tlast      ( ip_user_axis_tx_tlast       ),
      .ip_user_s_axis_tuser      ( ip_user_axis_tx_tuser       ),
      .ip_m_axis_tvalid          ( ip_axis_tx_tvalid           ),
      .ip_m_axis_tdata           ( ip_axis_tx_tdata            ),
      .ip_m_axis_tready          ( ip_axis_tx_tready           ),
      .ip_m_axis_tlast           ( ip_axis_tx_tlast            ),
      .ip_m_axis_tuser           ( ip_axis_tx_tuser            ),
      .ip_s_axis_tvalid          ( mac_user_axis_rx_tvalid     ),
      .ip_s_axis_tdata           ( mac_user_axis_rx_tdata      ),
      .ip_s_axis_tlast           ( mac_user_axis_rx_tlast      ),
      .ip_s_axis_tuser           ( mac_user_axis_rx_tuser      )
   );

   /*-----------------------------------------------------------
                     ENTHERNET ARP FUNCTION
   ------------------------------------------------------------*/
   ethernet_arp_top #(
      .SOURCE_MAC                ( SOURCE_MAC                  ),
      .SOURCE_IP                 ( SOURCE_IP                   )
   )ethernet_arp_top_inst(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_ip           ( i_config_source_ip          ),
      .i_set_source_ip_valid     ( i_config_req                ),
      .i_set_source_mac          ( i_config_source_mac         ),
      .i_set_source_mac_valid    ( i_config_req                ),
      .i_arp_req_ip              ( arp_req_ip                  ),
      .i_arp_req                 ( arp_req                     ),
      .o_arp_info_mac0           ( arp_info_mac0               ),
      .o_arp_info_ip0            ( arp_info_ip0                ),
      .o_arp_info_mac1           ( arp_info_mac1               ),
      .o_arp_info_ip1            ( arp_info_ip1                ), 
      .s_axis_tvalid             ( mac_user_axis_rx_tvalid     ),
      .s_axis_tdata              ( mac_user_axis_rx_tdata      ),
      .s_axis_tlast              ( mac_user_axis_rx_tlast      ),
      .s_axis_tuser              ( mac_user_axis_rx_tuser      ),
      .m_axis_tvalid             ( arp_axis_tx_tvalid          ),
      .m_axis_tdata              ( arp_axis_tx_tdata           ),
      .m_axis_tready             ( arp_axis_tx_tready          ),
      .m_axis_tlast              ( arp_axis_tx_tlast           ),
      .m_axis_tuser              ( arp_axis_tx_tuser           )  
   );

   /*-----------------------------------------------------------
                     mac tx arbitriter
   ------------------------------------------------------------*/
   arbiter2to1 mac_tx_arbiter2to1(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .s_axis_tvalid_0           ( arp_axis_tx_tvalid          ),
      .s_axis_tdata_0            ( arp_axis_tx_tdata           ),
      .s_axis_tready_0           ( arp_axis_tx_tready          ),
      .s_axis_tlast_0            ( arp_axis_tx_tlast           ),
      .s_axis_tuser_0            ( arp_axis_tx_tuser           ),
      .s_axis_tvalid_1           ( ip_axis_tx_tvalid           ),
      .s_axis_tdata_1            ( ip_axis_tx_tdata            ),
      .s_axis_tready_1           ( ip_axis_tx_tready           ),
      .s_axis_tlast_1            ( ip_axis_tx_tlast            ),
      .s_axis_tuser_1            ( ip_axis_tx_tuser            ),
      .m_axis_tvalid             ( mac_user_axis_tx_tvalid     ),
      .m_axis_tdata              ( mac_user_axis_tx_tdata      ),
      .m_axis_tready             ( mac_user_axis_tx_tready     ),
      .m_axis_tlast              ( mac_user_axis_tx_tlast      ),
      .m_axis_tuser              ( mac_user_axis_tx_tuser      )
   );
    
   /*-----------------------------------------------------------
                     ENTHERNET MAC LAYER
   ------------------------------------------------------------*/
   ethernet_mac_top #(
      .SOURCE_MAC                ( SOURCE_MAC                  ),
      .CRC_ON                    ( MAC_CRC_ON                  )      
   )ethernet_mac_top_inst(
      .i_clk                     ( i_clk                       ),
      .i_rst                     ( i_rst                       ),
      .i_set_source_mac          ( i_config_source_mac         ),
      .i_set_source_mac_valid    ( i_config_req                ),
      .i_arp_info_mac0           ( arp_info_mac0               ),
      .i_arp_info_ip0            ( arp_info_ip0                ),
      .i_arp_info_mac1           ( arp_info_mac1               ),
      .i_arp_info_ip1            ( arp_info_ip1                ),
      .m_axis_tvalid             ( mac_user_axis_rx_tvalid     ), 
      .m_axis_tdata              ( mac_user_axis_rx_tdata      ), 
      .m_axis_tlast              ( mac_user_axis_rx_tlast      ), 
      .m_axis_tuser              ( mac_user_axis_rx_tuser      ), 
      .s_axis_tvalid             ( mac_user_axis_tx_tvalid     ), 
      .s_axis_tdata              ( mac_user_axis_tx_tdata      ), 
      .s_axis_tready             ( mac_user_axis_tx_tready     ), 
      .s_axis_tlast              ( mac_user_axis_tx_tlast      ), 
      .s_axis_tuser              ( mac_user_axis_tx_tuser      ), 
      .i_gmii_rxdata             ( i_gmii_rxdata               ),
      .i_gmii_rxvalid            ( i_gmii_rxvalid              ),
      .o_gmii_txdata             ( o_gmii_txdata               ),
      .o_gmii_txvalid            ( o_gmii_txvalid              )
   );

    
   

endmodule
